package cn.stylefeng.guns.modular.business.util;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/*
    <dependency>
        <groupId>org.apache.httpcomponents</groupId>
        <artifactId>httpclient</artifactId>
    </dependency>
 */

/**
 * Http工具类
 */
@Component
@Slf4j
public class HttpUtil {

    /**
     * 发送post请求携带非json参数
     * @param url 请求地址
     * @param param 参数Map
     * @param headers 请求头Map
     * @return 响应结果
     */
    public String post(String url, Map<String, Object> param, Map<String, String> headers) {
        //1、创建HttpClient实例对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2、创建请求方式实例
        HttpPost httpPost = new HttpPost();
        try {
            //3、给请求方式实例注入url
            httpPost.setURI(new URI(url));
            //4、设置请求和传输的超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPost.setConfig(requestConfig);
            //5、设置请求参数
            if (Objects.nonNull(param) && !param.isEmpty()) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (Map.Entry<String, Object> entry : param.entrySet()) {
                    String key = entry.getKey();
                    String value = entry.getValue().toString();
                    BasicNameValuePair basicNameValuePair = new BasicNameValuePair(key, value);
                    paramList.add(basicNameValuePair);
                }
                UrlEncodedFormEntity urlEncodedFormEntity = new UrlEncodedFormEntity(paramList, "UTF-8");
                httpPost.setEntity(urlEncodedFormEntity);
            }
            //6、设置请求头
            httpPost.addHeader("Content-Type", "application/x-www-form-urlencoded");
            setReqHeader(httpPost, headers);
            //7、发送请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            //8、获取响应内容
            return parseResponse(response);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发送请求出现异常：{}", e.getMessage());
            return null;
        } finally {
            //关闭资源
            httpPost.abort();
            httpClient.getConnectionManager().shutdown();
        }
    }

    /**
     * 设置请求头
     * @param httpPost 请求方式对象
     * @param headers 请求头map
     */
    private void setReqHeader(HttpPost httpPost, Map<String, String> headers) {
        if (Objects.nonNull(headers) && !headers.isEmpty()) {
            for (Map.Entry<String, String> entry : headers.entrySet()) {
                httpPost.addHeader(entry.getKey(), entry.getValue());
            }
        }
    }

    /**
     * 发送post请求携带json参数
     * @param url 请求路径
     * @param jsonParam json请求参数
     * @param headers 请求头
     * @return 返回请求结果
     */
    public String post(String url, String jsonParam, Map<String, String> headers) {
        //1、创建HttpClient实例对象
        CloseableHttpClient httpClient = HttpClients.createDefault();
        //2、创建请求方式实例
        HttpPost httpPost = new HttpPost();
        try {
            //3、给请求方式实例注入url
            httpPost.setURI(new URI(url));
            //4、设置请求和传输的超时时间
            RequestConfig requestConfig = RequestConfig.custom()
                    .setSocketTimeout(60000)
                    .setConnectTimeout(60000).build();
            httpPost.setConfig(requestConfig);
            //5、设置请求参数
            httpPost.setEntity(new StringEntity(jsonParam, "UTF-8"));
            //6、设置请求头
            httpPost.addHeader("Content-Type", "application/json");
            setReqHeader(httpPost, headers);
            //7、发送请求
            CloseableHttpResponse response = httpClient.execute(httpPost);
            //8、获取响应内容
            return parseResponse(response);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("发送请求出现异常：{}", e.getMessage());
            return null;
        } finally {
            //关闭资源
            httpPost.abort();
            httpClient.getConnectionManager().shutdown();
        }
    }

    /**
     * 发送get请求
     * @param url 请求地址
     * @return String
     */
    public String get(String url) {
        //1、创建HttpClient实例对象
        CloseableHttpClient httpClient = HttpClientBuilder.create().build();
        //2、创建请求方式实例
        HttpGet httpGet = new HttpGet(url);
        //3、设置请求和传输的超时时间
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(60000)
                .setConnectTimeout(60000).build();
        httpGet.setConfig(requestConfig);
        try {
            //4、发送请求
            CloseableHttpResponse response = httpClient.execute(httpGet);
            //5、获取结果
            return parseResponse(response);
        } catch (IOException e) {
            e.printStackTrace();
            log.error("发送请求出现异常：{}", e.getMessage());
            return null;
        } finally {
            //释放资源
            httpGet.abort();
            httpClient.getConnectionManager().shutdown();
        }
    }

    /**
     * 解析响应结果
     * @param response CloseableHttpResponse
     * @return String
     */
    private String parseResponse(CloseableHttpResponse response) throws IOException {
        int statusCode = response.getStatusLine().getStatusCode();
        if (statusCode == 200) {
            return EntityUtils.toString(response.getEntity());
        } else {
            log.error("请求第三方接口出现错误，状态码为:{}", statusCode);
            return null;
        }
    }
}
